home *** CD-ROM | disk | FTP | other *** search
/ Freelog 125 / Freelog_MarsAvril2015_No125.iso / Musique / Quod Libet / quodlibet-3.3.0-installer.exe / bin / quodlibet / ext / events / mpdserver / main.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2014-12-31  |  31KB  |  876 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.7)
  3.  
  4. import re
  5. import shlex
  6. from gi.repository import GObject
  7. from quodlibet import const
  8. from tcpserver import BaseTCPServer, BaseTCPConnection
  9.  
  10. class AckError(object):
  11.     NOT_LIST = 1
  12.     ARG = 2
  13.     PASSWORD = 3
  14.     PERMISSION = 4
  15.     UNKNOWN = 5
  16.     NO_EXIST = 50
  17.     PLAYLIST_MAX = 51
  18.     SYSTEM = 52
  19.     PLAYLIST_LOAD = 53
  20.     UPDATE_ALREADY = 54
  21.     PLAYER_SYNC = 55
  22.     EXIST = 56
  23.  
  24. TAG_MAPPING = [
  25.     (u'Artist', 'artist'),
  26.     (u'ArtistSort', 'artistsort'),
  27.     (u'Album', 'album'),
  28.     (u'AlbumArtist', 'albumartist'),
  29.     (u'AlbumArtistSort', 'albumartistsort'),
  30.     (u'Title', 'title'),
  31.     (u'Track', 'tracknumber'),
  32.     (u'Name', ''),
  33.     (u'Genre', 'genre'),
  34.     (u'Date', '~year'),
  35.     (u'Composer', 'composer'),
  36.     (u'Performer', 'performer'),
  37.     (u'Comment', 'commend'),
  38.     (u'Disc', 'discnumber'),
  39.     (u'Time', '~#length'),
  40.     (u'Name', '~basename'),
  41.     (u'MUSICBRAINZ_ARTISTID', 'musicbrainz_artistid'),
  42.     (u'MUSICBRAINZ_ALBUMID', 'musicbrainz_albumid'),
  43.     (u'MUSICBRAINZ_ALBUMARTISTID', 'musicbrainz_albumartistid'),
  44.     (u'MUSICBRAINZ_TRACKID', 'musicbrainz_trackid')]
  45.  
  46. def format_tags(song):
  47.     '''Gives a tag list message for a song'''
  48.     lines = []
  49.     for mpd_key, ql_key in TAG_MAPPING:
  50.         if not ql_key:
  51.             continue
  52.         value = song.comma(ql_key) if ql_key.startswith('~#') else None
  53.         if value is not None:
  54.             lines.append(u'%s: %s' % (mpd_key, value))
  55.             continue
  56.     return u'\n'.join(lines)
  57.  
  58.  
  59. class ParseError(Exception):
  60.     pass
  61.  
  62.  
  63. def parse_command(line):
  64.     '''Parses a MPD command (without trailing newline)
  65.  
  66.     Returns (command, [arguments]) or raises ParseError in case of an error.
  67.     '''
  68.     if not isinstance(line, bytes):
  69.         raise AssertionError
  70.     parts = None.split('[ \\t]+', line, maxsplit = 1)
  71.     if not parts:
  72.         raise ParseError('empty command')
  73.     command = parts[0]
  74.     if len(parts) > 1:
  75.         lex = shlex.shlex(parts[1], posix = True)
  76.         lex.whitespace_split = True
  77.         lex.commenters = ''
  78.         lex.quotes = '"'
  79.         lex.whitespace = ' \t'
  80.         args = list(lex)
  81.     else:
  82.         args = []
  83.     
  84.     try:
  85.         command = command.decode('utf-8')
  86.     except ValueError:
  87.         e = None
  88.         raise ParseError(e)
  89.  
  90.     dec_args = []
  91.     for arg in args:
  92.         
  93.         try:
  94.             arg = arg.decode('utf-8')
  95.         except ValueError:
  96.             e = None
  97.             raise ParseError(e)
  98.  
  99.         dec_args.append(arg)
  100.     
  101.     return (command, dec_args)
  102.  
  103.  
  104. class PlayerOptions(GObject.Object):
  105.     '''Provides a simplified interface for playback options.
  106.  
  107.     This should probably go into the core.
  108.     '''
  109.     __gsignals__ = {
  110.         'random-changed': (GObject.SignalFlags.RUN_LAST, None, tuple()),
  111.         'repeat-changed': (GObject.SignalFlags.RUN_LAST, None, tuple()),
  112.         'single-changed': (GObject.SignalFlags.RUN_LAST, None, tuple()) }
  113.     
  114.     def __init__(self, app):
  115.         super(PlayerOptions, self).__init__()
  116.         self._repeat = app.window.repeat
  117.         self._rid = self._repeat.connect(('toggled',), (lambda : self.emit('repeat-changed')))
  118.         
  119.         def order_changed(*args):
  120.             self.emit('random-changed')
  121.             self.emit('single-changed')
  122.  
  123.         self._order = app.window.order
  124.         self._oid = self._order.connect('changed', order_changed)
  125.  
  126.     
  127.     def destroy(self):
  128.         self._repeat.disconnect(self._rid)
  129.         del self._repeat
  130.         self._order.disconnect(self._oid)
  131.         del self._order
  132.  
  133.     
  134.     def set_single(self, value):
  135.         is_single = self.get_single()
  136.         if value and not is_single:
  137.             self._order.set_active_by_name('onesong')
  138.         elif not value and is_single:
  139.             self._order.set_active_by_name('inorder')
  140.  
  141.     
  142.     def get_single(self):
  143.         return self._order.get_active_name() == 'onesong'
  144.  
  145.     
  146.     def get_random(self):
  147.         return self._order.get_shuffle()
  148.  
  149.     
  150.     def set_random(self, value):
  151.         self._order.set_shuffle(value)
  152.  
  153.     
  154.     def get_repeat(self):
  155.         return self._repeat.get_active()
  156.  
  157.     
  158.     def set_repeat(self, value):
  159.         self._repeat.set_active(value)
  160.  
  161.  
  162.  
  163. class MPDService(object):
  164.     '''This is the actual shared MPD service which the clients talk to'''
  165.     version = (0, 17, 0)
  166.     
  167.     def __init__(self, app):
  168.         self._app = app
  169.         self._connections = set()
  170.         self._idle_subscriptions = { }
  171.         self._pl_ver = 0
  172.         self._options = PlayerOptions(app)
  173.         
  174.         def options_changed(*args):
  175.             self.emit_changed('options')
  176.  
  177.         self._options.connect('random-changed', options_changed)
  178.         self._options.connect('repeat-changed', options_changed)
  179.         self._options.connect('single-changed', options_changed)
  180.         self._player_sigs = []
  181.         
  182.         def volume_changed(*args):
  183.             self.emit_changed('mixer')
  184.  
  185.         id_ = app.player.connect('notify::volume', volume_changed)
  186.         self._player_sigs.append(id_)
  187.         
  188.         def player_changed(*args):
  189.             self.emit_changed('player')
  190.  
  191.         id_ = app.player.connect('paused', player_changed)
  192.         self._player_sigs.append(id_)
  193.         id_ = app.player.connect('unpaused', player_changed)
  194.         self._player_sigs.append(id_)
  195.         id_ = app.player.connect('seek', player_changed)
  196.         self._player_sigs.append(id_)
  197.         
  198.         def playlist_changed(*args):
  199.             self._pl_ver += 1
  200.             self.emit_changed('playlist')
  201.  
  202.         id_ = app.player.connect('song-started', playlist_changed)
  203.         self._player_sigs.append(id_)
  204.  
  205.     
  206.     def _get_id(self, info):
  207.         return (id(info) & 0xFFFFFFFFL) >> 1
  208.  
  209.     
  210.     def destroy(self):
  211.         for id_ in self._player_sigs:
  212.             self._app.player.disconnect(id_)
  213.         
  214.         self._options.destroy()
  215.         del self._app
  216.         del self._options
  217.  
  218.     
  219.     def add_connection(self, connection):
  220.         self._connections.add(connection)
  221.  
  222.     
  223.     def remove_connection(self, connection):
  224.         self._idle_subscriptions.pop(connection, None)
  225.         self._connections.remove(connection)
  226.  
  227.     
  228.     def register_idle(self, connection, subsystems):
  229.         self._idle_subscriptions[connection] = subsystems
  230.  
  231.     
  232.     def unregister_idle(self, connection):
  233.         
  234.         try:
  235.             del self._idle_subscriptions[connection]
  236.         except KeyError:
  237.             pass
  238.  
  239.  
  240.     
  241.     def emit_changed(self, subsystem):
  242.         for conn, subs in self._idle_subscriptions.iteritems():
  243.             if not not subs:
  244.                 if subsystem in subs:
  245.                     line = u'changed: %s' % subsystem
  246.                     conn.log(u'<- ' + line)
  247.                     conn.write_line(line)
  248.                     conn.ok()
  249.                     conn.start_write()
  250.                     continue
  251.                 return None
  252.  
  253.     
  254.     def play(self):
  255.         if not self._app.player.song:
  256.             self._app.player.reset()
  257.         else:
  258.             self._app.player.paused = False
  259.  
  260.     
  261.     def playid(self, songid):
  262.         self.play()
  263.  
  264.     
  265.     def pause(self, value = None):
  266.         if value is None:
  267.             self._app.player.paused = not (self._app.player.paused)
  268.         else:
  269.             self._app.player.paused = value
  270.  
  271.     
  272.     def stop(self):
  273.         self._app.player.stop()
  274.  
  275.     
  276.     def next(self):
  277.         self._app.player.next()
  278.  
  279.     
  280.     def previous(self):
  281.         self._app.player.previous()
  282.  
  283.     
  284.     def seek(self, songpos, time_):
  285.         '''time_ in seconds'''
  286.         self._app.player.seek(time_ * 1000)
  287.  
  288.     
  289.     def seekid(self, songid, time_):
  290.         '''time_ in seconds'''
  291.         self._app.player.seek(time_ * 1000)
  292.  
  293.     
  294.     def seekcur(self, value, relative):
  295.         if relative:
  296.             pos = self._app.player.get_position()
  297.             self._app.player.seek(pos + value)
  298.         else:
  299.             self._app.player.seek(value)
  300.  
  301.     
  302.     def setvol(self, value):
  303.         '''value: 0..100'''
  304.         self._app.player.volume = value / 100
  305.  
  306.     
  307.     def repeat(self, value):
  308.         self._options.set_repeat(value)
  309.  
  310.     
  311.     def random(self, value):
  312.         self._options.set_random(value)
  313.  
  314.     
  315.     def single(self, value):
  316.         self._options.set_single(value)
  317.  
  318.     
  319.     def stats(self):
  320.         has_song = int(bool(self._app.player.info))
  321.         stats = [
  322.             ('artists', has_song),
  323.             ('albums', has_song),
  324.             ('songs', has_song),
  325.             ('uptime', 1),
  326.             ('playtime', 1),
  327.             ('db_playtime', 1),
  328.             ('db_update', 1252868674)]
  329.         return stats
  330.  
  331.     
  332.     def status(self):
  333.         app = self._app
  334.         info = app.player.info
  335.         if info:
  336.             if app.player.paused:
  337.                 state = 'pause'
  338.             else:
  339.                 state = 'play'
  340.         else:
  341.             state = 'stop'
  342.         status = [
  343.             ('volume', int(app.player.volume * 100)),
  344.             ('repeat', int(self._options.get_repeat())),
  345.             ('random', int(self._options.get_random())),
  346.             ('single', int(self._options.get_single())),
  347.             ('consume', 0),
  348.             ('playlist', self._pl_ver),
  349.             ('playlistlength', int(bool(app.player.info))),
  350.             ('mixrampdb', 0),
  351.             ('state', state)]
  352.         if info:
  353.             total_time = int(info('~#length'))
  354.             elapsed_time = int(app.player.get_position() / 1000)
  355.             elapsed_exact = '%1.3f' % app.player.get_position() / 1000
  356.             status.extend([
  357.                 ('song', 0),
  358.                 ('songid', self._get_id(info))])
  359.             if state != 'stop':
  360.                 status.extend([
  361.                     ('time', '%d:%d' % (elapsed_time, total_time)),
  362.                     ('elapsed', elapsed_exact),
  363.                     ('bitrate', info('~#bitrate'))])
  364.             
  365.         return status
  366.  
  367.     
  368.     def currentsong(self):
  369.         info = self._app.player.info
  370.         if info is None:
  371.             return None
  372.         parts = None
  373.         parts.append(u'file: %s' % info('~filename'))
  374.         parts.append(format_tags(info))
  375.         parts.append(u'Pos: 0')
  376.         parts.append(u'Id: %d' % self._get_id(info))
  377.         return u'\n'.join(parts)
  378.  
  379.     
  380.     def playlistinfo(self, start = None, end = None):
  381.         if start is not None and start > 1:
  382.             return None
  383.         return None.currentsong()
  384.  
  385.     
  386.     def playlistid(self, songid = None):
  387.         return self.currentsong()
  388.  
  389.     
  390.     def plchanges(self, version):
  391.         if version != self._pl_ver:
  392.             return self.currentsong()
  393.  
  394.     
  395.     def plchangesposid(self, version):
  396.         info = self._app.player.info
  397.         if version != self._pl_ver and info:
  398.             parts = []
  399.             parts.append(u'file: %s' % info('~filename'))
  400.             parts.append(u'Pos: 0')
  401.             parts.append(u'Id: %d' % self._get_id(info))
  402.             return u'\n'.join(parts)
  403.  
  404.  
  405.  
  406. class MPDServer(BaseTCPServer):
  407.     
  408.     def __init__(self, app, port):
  409.         self._app = app
  410.         super(MPDServer, self).__init__(port, MPDConnection, const.DEBUG)
  411.  
  412.     
  413.     def handle_init(self):
  414.         print_d('Creating the MPD service')
  415.         self.service = MPDService(self._app)
  416.  
  417.     
  418.     def handle_idle(self):
  419.         print_d('Destroying the MPD service')
  420.         self.service.destroy()
  421.         del self.service
  422.  
  423.     
  424.     def log(self, msg):
  425.         print_d(msg)
  426.  
  427.  
  428.  
  429. class MPDRequestError(Exception):
  430.     
  431.     def __init__(self, msg, code = AckError.UNKNOWN, index = None):
  432.         self.msg = msg
  433.         self.code = code
  434.         self.index = index
  435.  
  436.  
  437.  
  438. class MPDConnection(BaseTCPConnection):
  439.     
  440.     def handle_init(self, server):
  441.         service = server.service
  442.         self.service = service
  443.         service.add_connection(self)
  444.         str_version = '.'.join(map(str, service.version))
  445.         self._buf = bytearray('OK MPD %s\n' % str_version)
  446.         self._read_buf = bytearray()
  447.         self._use_command_list = False
  448.         self._command_list_ok = False
  449.         self._command_list = []
  450.         self._command = None
  451.         self.start_write()
  452.         self.start_read()
  453.  
  454.     
  455.     def handle_read(self, data):
  456.         self._feed_data(data)
  457.         while None:
  458.             line = self._get_next_line()
  459.             if line is None:
  460.                 break
  461.             
  462.             try:
  463.                 (cmd, args) = parse_command(line)
  464.             except ParseError:
  465.                 continue
  466.  
  467.             
  468.             try:
  469.                 self._handle_command(cmd, args)
  470.             continue
  471.             except MPDRequestError:
  472.                 e = None
  473.                 self._error(e.msg, e.code, e.index)
  474.                 self._use_command_list = False
  475.                 del self._command_list[:]
  476.                 continue
  477.             
  478.  
  479.             return None
  480.  
  481.     
  482.     def handle_write(self):
  483.         data = self._buf[:]
  484.         del self._buf[:]
  485.         return data
  486.  
  487.     
  488.     def can_write(self):
  489.         return bool(self._buf)
  490.  
  491.     
  492.     def handle_close(self):
  493.         self.log('connection closed')
  494.         self.service.remove_connection(self)
  495.         del self.service
  496.  
  497.     
  498.     def log(self, msg):
  499.         if const.DEBUG:
  500.             print_d('[%s] %s' % (self.name, msg))
  501.  
  502.     
  503.     def _feed_data(self, new_data):
  504.         '''Feed new data into the read buffer'''
  505.         self._read_buf.extend(new_data)
  506.  
  507.     
  508.     def _get_next_line(self):
  509.         '''Returns the next line from the read buffer or None'''
  510.         
  511.         try:
  512.             index = self._read_buf.index('\n')
  513.         except ValueError:
  514.             return None
  515.  
  516.         line = bytes(self._read_buf[:index])
  517.         del self._read_buf[:index + 1]
  518.         return line
  519.  
  520.     
  521.     def write_line(self, line):
  522.         '''Writes a line to the client'''
  523.         if not isinstance(line, unicode):
  524.             raise AssertionError
  525.         None._buf.extend(line.encode('utf-8', errors = 'replace') + '\n')
  526.  
  527.     
  528.     def ok(self):
  529.         self.write_line(u'OK')
  530.  
  531.     
  532.     def _error(self, msg, code, index):
  533.         error = []
  534.         error.append(u'ACK [%d' % code)
  535.         if index is not None:
  536.             error.append(u'@%d' % index)
  537.         if not self._command is not None:
  538.             raise AssertionError
  539.         None.append('u] {%s}' % self._command)
  540.         if msg is not None:
  541.             error.append(u' %s' % msg)
  542.         self.write_line(u''.join(error))
  543.  
  544.     
  545.     def _handle_command(self, command, args):
  546.         self._command = command
  547.         if command == u'command_list_end':
  548.             if not self._use_command_list:
  549.                 self._error(u'list_end without begin')
  550.                 return None
  551.             for cmd, args in enumerate(self._command_list):
  552.                 
  553.                 try:
  554.                     self._exec_command(cmd, args)
  555.                 continue
  556.                 except MPDRequestError:
  557.                     e = None
  558.                     raise MPDRequestError(e.msg, e.code, i)
  559.                     continue
  560.                 
  561.  
  562.             else:
  563.                 self._use_command_list = False
  564.                 del self._command_list[:]
  565.                 return None
  566.             if None in (u'command_list_begin', u'command_list_ok_begin'):
  567.                 if self._use_command_list:
  568.                     raise MPDRequestError(u'begin without end')
  569.                 self._use_command_list = True
  570.                 self._command_list_ok = command == u'command_list_ok_begin'
  571.                 if not not (self._command_list):
  572.                     raise AssertionError
  573.                 return None
  574.             if None._use_command_list:
  575.                 self._command_list.append((command, args))
  576.             else:
  577.                 self._exec_command(command, args)
  578.  
  579.     
  580.     def _exec_command(self, command, args, no_ack = False):
  581.         self._command = command
  582.         if command not in self._commands:
  583.             print_w('Unhandled command %r, sending OK.' % command)
  584.             command = 'ping'
  585.             if not self._use_command_list:
  586.                 self.ok()
  587.             elif self._command_list_ok:
  588.                 self.write_line(u'list_OK')
  589.             return None
  590.         (cmd, do_ack) = None._commands[command]
  591.         cmd(self, self.service, args)
  592.         if self._use_command_list or self._command_list_ok:
  593.             self.write_line(u'list_OK')
  594.         
  595.         if do_ack:
  596.             self.ok()
  597.  
  598.     _commands = { }
  599.     
  600.     def Command(cls, name, ack = True):
  601.         
  602.         def wrap(func):
  603.             if not name not in cls._commands:
  604.                 raise AssertionError(name)
  605.             cls._commands[name] = (None, ack)
  606.             return func
  607.  
  608.         return wrap
  609.  
  610.     Command = classmethod(Command)
  611.     
  612.     def list_commands(cls):
  613.         '''A list of supported commands'''
  614.         return cls._commands.keys()
  615.  
  616.     list_commands = classmethod(list_commands)
  617.  
  618.  
  619. def _verify_length(args, length):
  620.     if not len(args) >= length:
  621.         raise MPDRequestError('Wrong arg count')
  622.  
  623.  
  624. def _parse_int(arg):
  625.     
  626.     try:
  627.         return int(arg)
  628.     except ValueError:
  629.         raise MPDRequestError('invalid arg')
  630.  
  631.  
  632.  
  633. def _parse_bool(arg):
  634.     
  635.     try:
  636.         value = int(arg)
  637.         if value not in (0, 1):
  638.             raise ValueError
  639.     except ValueError:
  640.         raise MPDRequestError('invalid arg')
  641.  
  642.     return bool(value)
  643.  
  644.  
  645. def _parse_range(arg):
  646.     
  647.     try:
  648.         values = [ int(v) for v in arg.split(':') ]
  649.     except ValueError:
  650.         raise MPDRequestError('arg in range not a number')
  651.  
  652.     if len(values) == 1:
  653.         return (values[0], values[0] + 1)
  654.     if None(values) == 2:
  655.         return values
  656.     raise None('invalid range')
  657.  
  658.  
  659. def _cmd_idle(conn, service, args):
  660.     service.register_idle(conn, args)
  661.  
  662. _cmd_idle = MPDConnection.Command('idle', ack = False)(_cmd_idle)
  663.  
  664. def _cmd_ping(conn, service, args):
  665.     pass
  666.  
  667. _cmd_ping = MPDConnection.Command('ping')(_cmd_ping)
  668.  
  669. def _cmd_noidle(conn, service, args):
  670.     service.unregister_idle(conn)
  671.  
  672. _cmd_noidle = MPDConnection.Command('noidle')(_cmd_noidle)
  673.  
  674. def _cmd_close(conn, service, args):
  675.     conn.close()
  676.  
  677. _cmd_close = MPDConnection.Command('close', ack = False)(_cmd_close)
  678.  
  679. def _cmd_play(conn, service, args):
  680.     service.play()
  681.  
  682. _cmd_play = MPDConnection.Command('play')(_cmd_play)
  683.  
  684. def _cmd_playid(conn, service, args):
  685.     _verify_length(args, 1)
  686.     songid = _parse_int(args[0])
  687.     service.playid(songid)
  688.  
  689. _cmd_playid = MPDConnection.Command('playid')(_cmd_playid)
  690.  
  691. def _cmd_pause(conn, service, args):
  692.     value = None
  693.     if args:
  694.         _verify_length(args, 1)
  695.         value = _parse_bool(args[0])
  696.     service.pause(value)
  697.  
  698. _cmd_pause = MPDConnection.Command('pause')(_cmd_pause)
  699.  
  700. def _cmd_stop(conn, service, args):
  701.     service.stop()
  702.  
  703. _cmd_stop = MPDConnection.Command('stop')(_cmd_stop)
  704.  
  705. def _cmd_next(conn, service, args):
  706.     service.next()
  707.  
  708. _cmd_next = MPDConnection.Command('next')(_cmd_next)
  709.  
  710. def _cmd_previous(conn, service, args):
  711.     service.previous()
  712.  
  713. _cmd_previous = MPDConnection.Command('previous')(_cmd_previous)
  714.  
  715. def _cmd_repeat(conn, service, args):
  716.     _verify_length(args, 1)
  717.     value = _parse_bool(args[0])
  718.     service.repeat(value)
  719.  
  720. _cmd_repeat = MPDConnection.Command('repeat')(_cmd_repeat)
  721.  
  722. def _cmd_random(conn, service, args):
  723.     _verify_length(args, 1)
  724.     value = _parse_bool(args[0])
  725.     service.random(value)
  726.  
  727. _cmd_random = MPDConnection.Command('random')(_cmd_random)
  728.  
  729. def _cmd_single(conn, service, args):
  730.     _verify_length(args, 1)
  731.     value = _parse_bool(args[0])
  732.     service.single(value)
  733.  
  734. _cmd_single = MPDConnection.Command('single')(_cmd_single)
  735.  
  736. def _cmd_setvol(conn, service, args):
  737.     _verify_length(args, 1)
  738.     value = _parse_int(args[0])
  739.     service.setvol(value)
  740.  
  741. _cmd_setvol = MPDConnection.Command('setvol')(_cmd_setvol)
  742.  
  743. def _cmd_status(conn, service, args):
  744.     status = service.status()
  745.     for k, v in status:
  746.         conn.write_line(u'%s: %s' % (k, v))
  747.     
  748.  
  749. _cmd_status = MPDConnection.Command('status')(_cmd_status)
  750.  
  751. def _cmd_stats(conn, service, args):
  752.     status = service.stats()
  753.     for k, v in status:
  754.         conn.write_line(u'%s: %s' % (k, v))
  755.     
  756.  
  757. _cmd_stats = MPDConnection.Command('stats')(_cmd_stats)
  758.  
  759. def _cmd_currentsong(conn, service, args):
  760.     stats = service.currentsong()
  761.     if stats is not None:
  762.         conn.write_line(stats)
  763.  
  764. _cmd_currentsong = MPDConnection.Command('currentsong')(_cmd_currentsong)
  765.  
  766. def _cmd_count(conn, service, args):
  767.     conn.write_line(u'songs: 0')
  768.     conn.write_line(u'playtime: 0')
  769.  
  770. _cmd_count = MPDConnection.Command('count')(_cmd_count)
  771.  
  772. def _cmd_plchanges(conn, service, args):
  773.     _verify_length(args, 1)
  774.     version = _parse_int(args[0])
  775.     changes = service.plchanges(version)
  776.     if changes is not None:
  777.         conn.write_line(changes)
  778.  
  779. _cmd_plchanges = MPDConnection.Command('plchanges')(_cmd_plchanges)
  780.  
  781. def _cmd_plchangesposid(conn, service, args):
  782.     _verify_length(args, 1)
  783.     version = _parse_int(args[0])
  784.     changes = service.plchangesposid(version)
  785.     if changes is not None:
  786.         conn.write_line(changes)
  787.  
  788. _cmd_plchangesposid = MPDConnection.Command('plchangesposid')(_cmd_plchangesposid)
  789.  
  790. def _cmd_listallinfo(*args):
  791.     _cmd_currentsong(*args)
  792.  
  793. _cmd_listallinfo = MPDConnection.Command('listallinfo')(_cmd_listallinfo)
  794.  
  795. def _cmd_seek(conn, service, args):
  796.     _verify_length(args, 2)
  797.     songpos = _parse_int(args[0])
  798.     time_ = _parse_int(args[1])
  799.     service.seek(songpos, time_)
  800.  
  801. _cmd_seek = MPDConnection.Command('seek')(_cmd_seek)
  802.  
  803. def _cmd_seekid(conn, service, args):
  804.     _verify_length(args, 2)
  805.     songid = _parse_int(args[0])
  806.     time_ = _parse_int(args[1])
  807.     service.seekid(songid, time_)
  808.  
  809. _cmd_seekid = MPDConnection.Command('seekid')(_cmd_seekid)
  810.  
  811. def _cmd_seekcur(conn, service, args):
  812.     _verify_length(args, 1)
  813.     relative = False
  814.     time_ = args[0]
  815.     if time_.startswith(('+', '-')):
  816.         relative = True
  817.     
  818.     try:
  819.         time_ = int(time_)
  820.     except ValueError:
  821.         raise MPDRequestError('arg not a number')
  822.  
  823.     service.seekid(time_, relative)
  824.  
  825. _cmd_seekcur = MPDConnection.Command('seekcur')(_cmd_seekcur)
  826.  
  827. def _cmd_outputs(conn, service, args):
  828.     conn.write_line(u'outputid: 0')
  829.     conn.write_line(u'outputname: dummy')
  830.     conn.write_line(u'outputenabled: 1')
  831.  
  832. _cmd_outputs = MPDConnection.Command('outputs')(_cmd_outputs)
  833.  
  834. def _cmd_commands(conn, service, args):
  835.     for name in conn.list_commands():
  836.         conn.write_line(u'command: ' + unicode(name))
  837.     
  838.  
  839. _cmd_commands = MPDConnection.Command('commands')(_cmd_commands)
  840.  
  841. def _cmd_tagtypes(conn, service, args):
  842.     for mpd_key, ql_key in TAG_MAPPING:
  843.         if ql_key:
  844.             conn.write_line(mpd_key)
  845.             continue
  846.  
  847. _cmd_tagtypes = MPDConnection.Command('tagtypes')(_cmd_tagtypes)
  848.  
  849. def _cmd_lsinfo(conn, service, args):
  850.     _verify_length(args, 1)
  851.  
  852. _cmd_lsinfo = MPDConnection.Command('lsinfo')(_cmd_lsinfo)
  853.  
  854. def _cmd_playlistinfo(conn, service, args):
  855.     if args:
  856.         _verify_length(args, 1)
  857.         (start, end) = _parse_range(args[0])
  858.         result = service.playlistinfo(start, end)
  859.     else:
  860.         result = service.playlistinfo()
  861.     if result is not None:
  862.         conn.write_line(result)
  863.  
  864. _cmd_playlistinfo = MPDConnection.Command('playlistinfo')(_cmd_playlistinfo)
  865.  
  866. def _cmd_playlistid(conn, service, args):
  867.     if args:
  868.         songid = _parse_int(args[0])
  869.     else:
  870.         songid = None
  871.     result = service.playlistid(songid)
  872.     if result is not None:
  873.         conn.write_line(result)
  874.  
  875. _cmd_playlistid = MPDConnection.Command('playlistid')(_cmd_playlistid)
  876.